package mk.jug.academy.controller;

import java.text.MessageFormat;
import java.util.Properties;
import java.util.logging.Logger;

import mk.jug.academy.factory.EventFactory;
import mk.jug.academy.model.Course;
import mk.jug.academy.model.Page;
import mk.jug.academy.model.Student;
import mk.jug.academy.service.CourseService;
import mk.jug.academy.service.EventService;
import mk.jug.academy.service.StudentService;
import mk.jug.academy.util.Utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

/** View layer coordinator for the {@link Student} related functionality in the backend. */
@Controller
public class StudentAdminController extends BaseController {
		
	private static final Logger LOG = Logger.getLogger(StudentAdminController.class.getName());
	
	//TODO: Externalize this.
	public static final int itemsPerPage = 8;
	
	@Autowired private StudentService studentService;
	@Autowired private CourseService courseService;
	@Autowired private EventService eventService;
	@Autowired private Properties properties;
	
	private static String LIST_SIGNED_UP = "admin.students.signedup";
	private static String LIST_WAITING = "admin.students.waiting";
	private static String LIST_ENROLLED = "admin.students.enrolled";
	private static String LIST_REJECTED = "admin.students.rejected";
	private static String VIEW_STUDENT = "admin.students.view";
	
	@RequestMapping("/admin/students/signed_up.do")
	public String listSignedUp(final ModelMap map, final @RequestParam(value = "page", required = false) Integer p, final @RequestParam(value = "highlightID", required = false) String highlightID) {
		return new ControllerContext(map) {
			public String execute() {
				Integer page = p;
				if (page == null) {
					page = 1;
				}
				Page<Student> pagedStudents = studentService.listSignedUp(page, itemsPerPage);
				map.addAttribute("students", pagedStudents.getItems());
				map.addAttribute("pages", Utils.getPageNumber(itemsPerPage, pagedStudents.getTotalCount()));
				map.addAttribute("page", page);
				map.addAttribute("highlightID", highlightID);
				return LIST_SIGNED_UP;
			}
		}.result();
	}
	
	@RequestMapping("/admin/students/view.do")
	public String view(final ModelMap map, final @RequestParam("id") Long id) {
		return new ControllerContext(map) {
			public String execute() {
				map.addAttribute("student", studentService.load(id));
				return VIEW_STUDENT;
			}
		}.result();
	}
	
	@RequestMapping("/admin/students/accept.do")
	public String acceptRegistration(final ModelMap map, final @RequestParam("id") Long id) {
		return new ControllerContext(map) {
			public String execute() {
				Student student = studentService.load(id);
				studentService.approveRegistration(student);
				LOG.fine("Student [" + student.getCode() + "] has been approved.");
				eventService.createEvent(EventFactory.acceptStudentEvent(student));
				String subject = properties.getProperty("activation.student.email.subject");
				String body = MessageFormat.format(properties.getProperty("activation.student.email.body"), new Object[] {student.getDisplayName()});
				Utils.sendMail(new String[] {student.getEmail(), student.getDisplayName()}, subject, body);
				return "redirect:/admin/students/signed_up.do";
			}
		}.result();
	}
	
	@RequestMapping("/admin/students/reject.do")
	public String rejectRegistration(final ModelMap map, final @RequestParam("id") Long id) {
		return new ControllerContext(map) {
			public String execute() {
				Student student = studentService.load(id);
				studentService.denyRegistration(student);
				LOG.info("Student registration has been denied [" + student.getCode() + "]");				
				return "redirect:/admin/students/signed_up.do";
			}
		}.result();
	}	
	
	@RequestMapping("/admin/students/waiting.do")
	public String listWaiting(final ModelMap map, final @RequestParam(value = "page", required = false) Integer p, final @RequestParam(value = "highlightID", required = false) String highlightID) {
		return new ControllerContext(map) {
			public String execute() {
				Integer page = p;
				if (page == null) {
					page = 1;
				}
				Page<Student> pagedStudents = studentService.listWaitingForEnrollment(page, itemsPerPage);
				map.addAttribute("students", pagedStudents.getItems());
				map.addAttribute("availableCourses", courseService.fetchAvailable());
				map.addAttribute("pages", Utils.getPageNumber(itemsPerPage, pagedStudents.getTotalCount()));
				map.addAttribute("page", page);
				map.addAttribute("highlightID", highlightID);
				return LIST_WAITING;
			}
		}.result();
	}
	
	@RequestMapping("/admin/students/enrollToCourse.do")
	public String enrollToCourse(final ModelMap map, final @RequestParam("courseID") Long courseID, final @RequestParam("studentID") Long studentID) {
		return new ControllerContext(map) {
			public String execute() {
				Student student = studentService.load(studentID);
				Course course = courseService.load(courseID);
				courseService.assignStudent(course, student);
				return "redirect:/admin/students/enrolled.do?highlightID=" + studentID;
			}
		}.result();
	}
	
	@RequestMapping("/admin/students/enrolled.do")
	public String listEnrolled(final ModelMap map, final @RequestParam(value = "page", required = false) Integer p, final @RequestParam(value = "highlightID", required = false) String highlightID) {
		return new ControllerContext(map) {
			public String execute() {
				Integer page = p;
				if (page == null) {
					page = 1;
				}
				Page<Student> pagedStudents = studentService.listEnrolled(page, itemsPerPage);
				map.addAttribute("students", pagedStudents.getItems());
				map.addAttribute("pages", Utils.getPageNumber(itemsPerPage, pagedStudents.getTotalCount()));
				map.addAttribute("page", page);
				map.addAttribute("highlightID", highlightID);
				return LIST_ENROLLED;
			}
		}.result();
	}
	
	@RequestMapping("/admin/students/rejected.do")
	public String listRejected(final ModelMap map, final @RequestParam(value = "page", required = false) Integer p, final @RequestParam(value = "highlightID", required = false) String highlightID) {
		return new ControllerContext(map) {
			public String execute() {
				Integer page = p;
				if (page == null) {
					page = 1;
				}
				Page<Student> pagedStudents = studentService.listRejected(page, itemsPerPage);
				map.addAttribute("students", pagedStudents.getItems());
				map.addAttribute("pages", Utils.getPageNumber(itemsPerPage, pagedStudents.getTotalCount()));
				map.addAttribute("page", page);
				map.addAttribute("highlightID", highlightID);
				return LIST_REJECTED;
			}
		}.result();
	}	

}